﻿package com.winmastergames.multiplayer{
	import com.winmastergames.lolgame.mapDefault;
	import flash.display.*;
	import flash.events.*;
	import flash.geom.Rectangle;
	import flash.net.*;
	import flash.text.*;
	import com.winmastergames.multiplayer.messageObject;
	import com.winmastergames.lolgame.player;
	import flash.display.MovieClip;
	import com.winmastergames.lolgame.mapDefault;
	
	public class SocketClient extends Sprite {
		private var host:String;
		private var port:int;
		private var socket:Socket;
		private var chatArea:TextField;
		private var currentClientArray:Array = new Array();
		private var stageReference:mapDefault;
		private var stageRoot:Stage;
		
		public function SocketClient(h:String, 
								   p:int,  
								   mapRef:mapDefault,
								   stageRef:Stage) {
			this.host = h;
			this.port = p;
			this.stageRoot = stageRef;
			addEventListener(Event.ENTER_FRAME, loop);
			stageReference = mapRef;
		}
		
		public function loop(e:Event)
		{
			parseClients();
		}
		
		public function parseClients():void
		{
			for (var i:int = 0; i < currentClientArray.length; i++)
			{
				var tempMsg:messageObject = currentClientArray[i];
				tempMsg.clientPlayer.MClip.x = tempMsg.clientPlayer.X;
				tempMsg.clientPlayer.MClip.y = tempMsg.clientPlayer.Y;
			}
		}
		
		public function sendMessage(msg:String):void {
			msg += "\n";
			
			try {
				this.socket.writeUTFBytes(msg);
				this.socket.flush();
			}
			catch(e:Error) {
				trace("Error sending data: " + e);
			}
		}
		
		private function receiveData(msg:String):void {
			parseMessage(msg);
		}
		
		private function parseMessage(msg:String):void {
			var rMessage:String = msg;
			var dataArray:Array = rMessage.split(":");
			var argArray:Array = new Array();
			for(var i:int = 0; i < dataArray.length; i++)
			{
				if(i >= 2)
				{
					argArray.push(dataArray[i]);
				}
			}
			//Create MessageObject
			var msgObj:messageObject = new messageObject();
			msgObj.argumentArray = argArray;
			msgObj.rawDataArray = dataArray;
			msgObj.clientData.address = dataArray[0];
			msgObj.clientData.port = int(dataArray[1]);
			for (var j:int = 0; j < argArray.length; j++)
			{
				var tempArg:String = argArray[j];
				var tempArgArr:Array = tempArg.split("-");
				switch(tempArgArr[0])
				{
					case "X":
						msgObj.clientPlayer.X = int(tempArgArr[1]);
						break;
					case "Y":
						msgObj.clientPlayer.Y = int(tempArgArr[1]);
						break;
				}
			}
			//Send for Parsing
			if (msgObj.argumentArray.length >= 1)
			{
				parseMessageObject(msgObj);
			}
		}
		
		public function parseMessageObject(input:messageObject)
		{
			var duplicate:Boolean = false;
			var duplicateIndex:int = -1;
			for (var i:int = 0; i < currentClientArray.length; i++)
			{
				var tempArr:messageObject = currentClientArray[i];
				if (tempArr.clientData.address == input.clientData.address &&
					tempArr.clientData.port == input.clientData.port)
				{
					duplicate = true;
					duplicateIndex = i;
				}
			}
			//Not Already in Database just add to end.
			if (duplicate == false)
			{
				input.clientPlayer.MClip = new player(stageRoot);
				input.clientPlayer.MClip.x = input.clientPlayer.X;
				input.clientPlayer.MClip.y = input.clientPlayer.Y;
				stageReference.addChild(input.clientPlayer.MClip);
				currentClientArray.push(input);
			}
			//Already in Database check if different if its different splice
			//and add new information.
			if (duplicate == true)
			{
				var tempPlayer:messageObject = currentClientArray[duplicateIndex];
				input.clientPlayer.MClip = tempPlayer.clientPlayer.MClip;
				currentClientArray.splice(duplicateIndex, 1);
				currentClientArray.push(input);
			}
		}
		
		public function connect():Boolean {
			this.socket = new Socket(this.host, this.port);
			this.socket.addEventListener(Event.CONNECT, socketConnect);
			this.socket.addEventListener(Event.CLOSE, socketClose);
			this.socket.addEventListener(IOErrorEvent.IO_ERROR, socketError);
			this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
			this.socket.addEventListener(ProgressEvent.SOCKET_DATA, socketData);
				
			try {
				this.socket.connect(this.host, this.port);
			}
			catch (e:Error) {
				trace("Error on connect: " + e);
				
				return false;
			}
			
			return true;
		}
		
		public function closeSock():void {
			try {
				this.socket.close();
			}
			catch(e:Error) {
				trace("Error on close: " + e);
			}
		}
		
		private function socketConnect(event:Event):void {
			trace("Connected!");
		}

		private function socketData(event:ProgressEvent):void {
			receiveData(this.socket.readUTFBytes(this.socket.bytesAvailable));
		}
		
		private function socketClose(event:Event):void {
			trace("Connection closed: " + event);
		}
		
		private function socketError(event:IOErrorEvent):void {
			trace("Socket error: " + event);
		}
		
		private function securityError(event:SecurityErrorEvent):void {
			trace("Security error: " + event);
		}
		public function duplicateDisplayObject(target:DisplayObject, autoAdd:Boolean = false):DisplayObject {
			// create duplicate
			var targetClass:Class = Object(target).constructor;
			var duplicate:DisplayObject = new targetClass();
        
			// duplicate properties
			duplicate.transform = target.transform;
			duplicate.filters = target.filters;
			duplicate.cacheAsBitmap = target.cacheAsBitmap;
			duplicate.opaqueBackground = target.opaqueBackground;
			if (target.scale9Grid) {
				var rect:Rectangle = target.scale9Grid;
				// WAS Flash 9 bug where returned scale9Grid is 20x larger than assigned
				// rect.x /= 20, rect.y /= 20, rect.width /= 20, rect.height /= 20;
				duplicate.scale9Grid = rect;
			}
        
			// add to target parent's display list
			// if autoAdd was provided as true
			if (autoAdd && target.parent) {
				target.parent.addChild(duplicate);
			}
			return duplicate;
		}
	}
}